using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

using Athena;
using Athena.Tools;
using Athena.Objects;
using Athena.Core;

using WeifenLuo.WinFormsUI.Docking;
using System.Windows.Forms;

namespace Athena.Plugins
{
    public partial class PartWindow : IGUITool
    {
        public PartWindow()
        {
            _bRequiresNewToolWindow = false;

            InitializeComponent();

            InitializePartsList();

            Text = "Parts Window";
            ToolManager.Instance.RegisterTool(Text, "Allows adding of parts to the model", this);
            PartsRegistry.Instance.PartsChanged += new PartsRegistry.PartsChangedDelegate(Instance_PartsChanged);

        }

        void Instance_PartsChanged(object sender, EventArgs e)
        {
            InitializePartsList();
        }

        /// <summary>
        /// Hashtable mapping group types to ListViewGroups
        /// </summary>
        Hashtable _oGroups = new Hashtable();
        /// <summary>
        /// Hashtable mapping part id's to Idrawables
        /// </summary>
        Hashtable _oParts = new Hashtable();
        /// <summary>
        /// Hashtable mapping part id's to image list indices
        /// </summary>
        Hashtable _oImages = new Hashtable();

        ImageList _oImageList = new ImageList();

        private bool HaveGroup(string sId)
        {
            return _oGroups.ContainsKey(sId);
        }
        private ListViewGroup GetGroup(string sId)
        {
            if (!_oGroups.ContainsKey(sId))
                throw new ArgumentException("No group for " + sId + "exists ... ");
            return (ListViewGroup)_oGroups[sId];
        }

        private IDrawable GetPart(string sId)
        {
            return (IDrawable)_oParts[sId];
        }

        public string GetGroupType(IDrawable item)
        {
            if (item.Item == null) return "";
            return item.Item.ItemType;
        }

        private void InitializePart(IDrawable drawable)
        {
            try
            {
                string sGroup = GetGroupType(drawable);
                ListViewItem oListItem = new ListViewItem();

                string sId = drawable.Item.ID;

                if (_oParts.ContainsKey(sId))
                {
                    return;
                }

                oListItem.Text = sId;
                _oParts.Add(sId, drawable);


                // add image if we can get one
                if (drawable is IGlyph)
                {
                    IGlyph oGlyph = drawable as IGlyph;
                    if (oGlyph.HasPreview)
                    {
                        int nIndex = _oImageList.Images.Add(oGlyph.GetPreview(Math.Max((int)oGlyph.Dimensions.Width, 20), Math.Max((int)oGlyph.Dimensions.Height, 20)), System.Drawing.Color.Transparent);
                        oListItem.ImageIndex = nIndex;
                    }
                }

                // add new group if we don't have one
                if (!HaveGroup(sGroup))
                {
                    ListViewGroup oGroup = new ListViewGroup(sGroup, HorizontalAlignment.Left);
                    listView1.Groups.Add(oGroup);
                    _oGroups.Add(sGroup, oGroup);
                }
                oListItem.Group = GetGroup(sGroup);

                // and add the item ... voila
                listView1.Items.Add(oListItem);
            }
            catch (Exception)
            {
                ///
            }
        }
        private void InitializePartsList()
        {
            // first clear everything we have ... 
            _oImages = new Hashtable();
            _oImageList = new ImageList();
            listView1.Items.Clear();
            listView1.Groups.Clear();            
            
            _oGroups = new Hashtable();
            _oParts = new Hashtable();

            // next initialize groups
            List<IDrawable> oItems = PartsRegistry.Instance.Parts;
            foreach (IDrawable drawable in oItems)
            {
                if (drawable.Item == null || string.IsNullOrEmpty(drawable.Item.ID)) continue;
                InitializePart(drawable);
            }

            // assign our images ... 
            listView1.LargeImageList = _oImageList;
            listView1.SmallImageList = _oImageList;
            

            // and don't forget to update ... 
            listView1.Refresh();

        }

        public override void SetupDockPanel(WeifenLuo.WinFormsUI.Docking.DockPanel oPanel)
        {
            this.DockPanel = oPanel;
        }
        public override void SetupToolStrip(ToolStrip oStrip)
        {
            //ToolStripButton oButton = new ToolStripButton();
            //oButton.Text = "P&arts ...";
            //oButton.ToolTipText = "Allows adding of parts to the model";
            //oButton.Click += new EventHandler(ShowHide_Click);
            //oStrip.Items.Add(oButton);
        }

        public override void ShowHide_Click(object sender, EventArgs e)
        {
            if (IsHidden)
            {
                //DockState = DockState.DockLeft;
                Show();
            }
            else
            {
                Hide();
            }
        }

        private void listView1_DragEnter(object sender, DragEventArgs e)
        {
            listView1_DragOver(sender, e);
        }

        private void listView1_DragDrop(object sender, DragEventArgs e)
        {
            List<IDrawable> oData = (List<IDrawable>)e.Data.GetData(typeof(List<IDrawable>));
            if (oData != null && oData.Count > 0)
            foreach (IDrawable drawable in oData)
            {
                PartsRegistry.Instance.AddPart(drawable);
            }           
        }

        private void listView1_DragOver(object sender, DragEventArgs e)
        {
            // Determine whether string data exists in the drop data. If not, then
            // the drop effect reflects that the drop cannot occur.
            if (!e.Data.GetDataPresent(typeof(List<IDrawable>)))
            {

                e.Effect = DragDropEffects.None;
                return;
            }


            List<IDrawable> oData = (List<IDrawable>)e.Data.GetData(typeof(List<IDrawable>));

            if (oData != null && oData.Count > 0)
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;

        }

        private void listView1_MouseDown(object sender, MouseEventArgs e)
        {
            ListView list = (ListView)sender;            
            System.Drawing.Point point = list.PointToClient(e.Location);
            ListViewItem oItem = list.GetItemAt(e.X, e.Y);
            //GetItemAt(point.X, point.Y);
            if (oItem != null)
            {
                Utility.SetMessage("DoDragDrop " + oItem.Text);
                listView1.DoDragDrop(oItem.Text, DragDropEffects.Copy);
            }
        }

        private void listView1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (MessageBox.Show("Do you really want to delete the selected parts?", "Delete Parts ... ", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    List<string> oList = new List<string>();
                    foreach (ListViewItem item in listView1.SelectedItems)
                    {
                        oList.Add(item.Text);
                    }                    
                    PartsRegistry.Instance.RemoveParts(oList);                    
                    
                }
            }
        }
    }
}
